From 506e6d7f5363ba691f81b65294c07061e48524c5 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Mon, 12 Mar 2007 11:15:56 +0000 Subject: [PATCH] AMD HVM: Exit hvmloader via a normal jump-to-realmode code sequence. Strip out all SVM-special hypercall code. Signed-off-by: Keir Fraser --- tools/firmware/hvmloader/hvmloader.c | 71 ++++++++++++++------------- xen/arch/x86/hvm/svm/svm.c | 69 +++----------------------- xen/include/asm-x86/hvm/svm/vmmcall.h | 44 ----------------- 3 files changed, 45 insertions(+), 139 deletions(-) delete mode 100644 xen/include/asm-x86/hvm/svm/vmmcall.h diff --git a/tools/firmware/hvmloader/hvmloader.c b/tools/firmware/hvmloader/hvmloader.c index bed26597ca..6b75303477 100644 --- a/tools/firmware/hvmloader/hvmloader.c +++ b/tools/firmware/hvmloader/hvmloader.c @@ -38,23 +38,47 @@ #define VMXASSIST_PHYSICAL_ADDRESS 0x000D0000 #define ROMBIOS_PHYSICAL_ADDRESS 0x000F0000 -/* invoke SVM's paged realmode support */ -#define SVM_VMMCALL_RESET_TO_REALMODE 0x80000001 - -/* - * C runtime start off - */ asm( " .text \n" " .globl _start \n" "_start: \n" + /* C runtime kickoff. */ " cld \n" " cli \n" - " lgdt gdt_desr \n" - " movl $stack_top, %esp \n" - " movl %esp, %ebp \n" + " movl $stack_top,%esp \n" + " movl %esp,%ebp \n" " call main \n" - " ud2 \n" + /* Relocate real-mode trampoline to 0x0. */ + " mov $trampoline_start,%esi \n" + " xor %edi,%edi \n" + " mov $trampoline_end,%ecx \n" + " sub %esi,%ecx \n" + " rep movsb \n" + /* Load real-mode compatible segment state (base 0x0000, limit 0xffff). */ + " lgdt gdt_desr \n" + " mov $0x0010,%ax \n" + " mov %ax,%ds \n" + " mov %ax,%es \n" + " mov %ax,%fs \n" + " mov %ax,%gs \n" + " mov %ax,%ss \n" + " ljmp $0x8,$0x0 \n" + /* Enter real mode, reload all segment registers and IDT. */ + "trampoline_start: .code16 \n" + " mov %cr0,%eax \n" + " and $0xfe,%al \n" + " mov %eax,%cr0 \n" + " ljmp $0,$1f-trampoline_start\n" + "1: xor %ax,%ax \n" + " mov %ax,%ds \n" + " mov %ax,%es \n" + " mov %ax,%fs \n" + " mov %ax,%gs \n" + " mov %ax,%ss \n" + " lidt 1f-trampoline_start \n" + " ljmp $0xf000,$0xfff0 \n" + "1: .word 0x3ff,0,0 \n" + "trampoline_end: .code32 \n" " \n" "gdt_desr: \n" " .word gdt_end - gdt - 1 \n" @@ -63,8 +87,8 @@ asm( " .align 8 \n" "gdt: \n" " .quad 0x0000000000000000 \n" - " .quad 0x00CF92000000FFFF \n" - " .quad 0x00CF9A000000FFFF \n" + " .quad 0x00009a000000ffff \n" /* Ring 0 code, base 0 limit 0xffff */ + " .quad 0x000092000000ffff \n" /* Ring 0 data, base 0 limit 0xffff */ "gdt_end: \n" " \n" " .bss \n" @@ -83,19 +107,6 @@ cirrus_check(void) return inb(0x3C5) == 0x12; } -static int -vmmcall(int function, int edi, int esi, int edx, int ecx, int ebx) -{ - int eax; - - __asm__ __volatile__ ( - ".byte 0x0F,0x01,0xD9" - : "=a" (eax) - : "a"(function), - "b"(ebx), "c"(ecx), "d"(edx), "D"(edi), "S"(esi) ); - return eax; -} - static int check_amd(void) { @@ -349,13 +360,7 @@ int main(void) ASSERT((ACPI_PHYSICAL_ADDRESS + acpi_sz) <= 0xF0000); } - if ( check_amd() ) - { - /* AMD implies this is SVM */ - printf("SVM go ...\n"); - vmmcall(SVM_VMMCALL_RESET_TO_REALMODE, 0, 0, 0, 0, 0); - } - else + if ( !check_amd() ) { printf("Loading VMXAssist ...\n"); memcpy((void *)VMXASSIST_PHYSICAL_ADDRESS, @@ -368,7 +373,7 @@ int main(void) ); } - printf("Failed to invoke ROMBIOS\n"); + printf("Invoking ROMBIOS ...\n"); return 0; } diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c index 0766ca5de2..c6faddcd95 100644 --- a/xen/arch/x86/hvm/svm/svm.c +++ b/xen/arch/x86/hvm/svm/svm.c @@ -43,7 +43,6 @@ #include #include #include -#include #include #include #include @@ -2591,65 +2590,6 @@ static int svm_do_vmmcall_reset_to_realmode(struct vcpu *v, } -/* - * svm_do_vmmcall - SVM VMMCALL handler - * - * returns 0 on success, non-zero otherwise - */ -static int svm_do_vmmcall(struct vcpu *v, struct cpu_user_regs *regs) -{ - struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; - int inst_len; - - ASSERT(vmcb); - ASSERT(regs); - - inst_len = __get_instruction_length(v, INSTR_VMCALL, NULL); - ASSERT(inst_len > 0); - - HVMTRACE_1D(VMMCALL, v, regs->eax); - - if ( regs->eax & 0x80000000 ) - { - /* VMMCALL sanity check */ - if ( vmcb->cpl > get_vmmcall_cpl(regs->edi) ) - { - printk("VMMCALL CPL check failed\n"); - return -1; - } - - /* handle the request */ - switch ( regs->eax ) - { - case VMMCALL_RESET_TO_REALMODE: - if ( svm_do_vmmcall_reset_to_realmode(v, regs) ) - { - printk("svm_do_vmmcall_reset_to_realmode() failed\n"); - return -1; - } - /* since we just reset the VMCB, return without adjusting - * the eip */ - return 0; - - case VMMCALL_DEBUG: - printk("DEBUG features not implemented yet\n"); - break; - default: - break; - } - - hvm_print_line(v, regs->eax); /* provides the current domain */ - } - else - { - hvm_do_hypercall(regs); - } - - __update_guest_eip(vmcb, inst_len); - return 0; -} - - void svm_dump_inst(unsigned long eip) { u8 opcode[256]; @@ -3152,9 +3092,14 @@ asmlinkage void svm_vmexit_handler(struct cpu_user_regs *regs) svm_handle_invlpg(1, regs); break; - case VMEXIT_VMMCALL: - svm_do_vmmcall(v, regs); + case VMEXIT_VMMCALL: { + int inst_len = __get_instruction_length(v, INSTR_VMCALL, NULL); + ASSERT(inst_len > 0); + HVMTRACE_1D(VMMCALL, v, regs->eax); + __update_guest_eip(vmcb, inst_len); + hvm_do_hypercall(regs); break; + } case VMEXIT_CR0_READ: svm_cr_access(v, 0, TYPE_MOV_FROM_CR, regs); diff --git a/xen/include/asm-x86/hvm/svm/vmmcall.h b/xen/include/asm-x86/hvm/svm/vmmcall.h deleted file mode 100644 index 7587bab7c6..0000000000 --- a/xen/include/asm-x86/hvm/svm/vmmcall.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * vmmcall.h: VMMCALL instruction support - * - * Travis Betak, travis.betak@amd.com - * Copyright (c) 2005, AMD Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 Temple - * Place - Suite 330, Boston, MA 02111-1307 USA. - * - */ - -#ifndef __ASM_X86_HVM_SVM_VMMCALL_H__ -#define __ASM_X86_HVM_SVM_VMMCALL_H__ - -/* VMMCALL command fields */ -#define VMMCALL_CODE_CPL_MASK 0x60000000 -#define VMMCALL_CODE_MBZ_MASK 0x1FFF0000 -#define VMMCALL_CODE_COMMAND_MASK 0x0000FFFF - -#define MAKE_VMMCALL_CODE(cpl,func) ((cpl << 29) | (func) | 0x80000000) - -/* CPL=0 VMMCALL Requests */ -#define VMMCALL_RESET_TO_REALMODE MAKE_VMMCALL_CODE(0,1) - -/* CPL=3 VMMCALL Requests */ -#define VMMCALL_DEBUG MAKE_VMMCALL_CODE(3,1) - -/* return the cpl required for the vmmcall cmd */ -static inline int get_vmmcall_cpl(int cmd) -{ - return (cmd & VMMCALL_CODE_CPL_MASK) >> 29; -} - -#endif /* __ASM_X86_HVM_SVM_VMMCALL_H__ */ -- 2.30.2